/*
     Copyright (C) Steve Martin, 2011.
              
*/

/*! \file encoder_wheel.c \brief Encoder Thumbwheel State Machine */

#include "encoder_wheel.h"
#define Button_Up		4
#define	Button_Down		3
#define Wheel_Up		2
#define Wheel_Down		1
#define Wheel_NoChange	0
#define Wheel_Resting	((1 << WHEEL_A) | (1 << WHEEL_B))
#define Wheel_MovingA	(1 << WHEEL_A)
#define Wheel_MovingB	(1 << WHEEL_B)
#define Wheel_Center	0

/****************************************************************************
*				Encoder Wheel Initialization								*
*****************************************************************************/
void		Initialize_Wheel(void)
{			cbi(WHEEL_DDR, WHEEL_A);		// Clear Quadrature A's DDR bit - Sets to Input Mode
			cbi(WHEEL_DDR, WHEEL_B);		// Clear Quadrature B's DDR bit - Sets to Input Mode
			cbi(WHEEL_SW_DDR, WHEEL_SW);	// Clear The wheel Switch's DDR bit - Sets to Input Mode
			
			sbi(WHEEL_PORT, WHEEL_A);		// Setting the pin to go high in input mode enables the pull up resistor
			sbi(WHEEL_PORT, WHEEL_B);		// Setting the pin to go high in input mode enables the pull up resistor
			sbi(WHEEL_SW_PORT, WHEEL_SW);	// Setting the pin to go high in input mode enables the pull up resistor
}
/****************************************************************************
*		Get Encoder Wheel and Push Button Values							*
*****************************************************************************/
u08			wheel_state(void)
{
			return inb(WHEEL_PINS) & ((1 << WHEEL_A) | (1 << WHEEL_B));
}

/****************************************************************************
*				Encoder Wheel State Machine									*
*		This function is called on pin change interrupts and returns: 		*
*				0: No Change or State Machine Reset due to Overrun			*
*				1: Wheel Down (Counterclockwise Turn)						*
*				2: Wheel Up   (Clockwise Turn)								*
*****************************************************************************/
u08 decode_wheel(u08 new_wheel_state)
{
static u08	old_wheel_state = Wheel_Resting;
static u08	wheel_up_state, wheel_dn_state = 0;

		switch (old_wheel_state)
		{	case Wheel_Resting:		{if      (new_wheel_state == Wheel_MovingA && wheel_dn_state == 0) {wheel_dn_state++;}
									else if (new_wheel_state == Wheel_MovingB && wheel_up_state == 0) {wheel_up_state++;}}
			break;

			case Wheel_MovingB:		{if      (new_wheel_state == Wheel_Resting && wheel_dn_state == 3) {wheel_dn_state++;}
									else if (new_wheel_state == Wheel_Center && wheel_up_state == 1) {wheel_up_state++;}}
			break;

			case Wheel_MovingA:		{if      (new_wheel_state == Wheel_Center && wheel_dn_state == 1) {wheel_dn_state++;}
									else if (new_wheel_state == Wheel_Resting && wheel_up_state == 3) {wheel_up_state++;}}
			break;

			case Wheel_Center:		{if      (new_wheel_state == Wheel_MovingB && wheel_dn_state == 2) {wheel_dn_state++;}
									else if (new_wheel_state == Wheel_MovingA && wheel_up_state == 2) {wheel_up_state++;}}
			break;

		}
		old_wheel_state = new_wheel_state;
		if		(wheel_up_state == 4)	{wheel_up_state = 0;
										 old_wheel_state = Wheel_Resting;
										return Wheel_Up;}

		else if	(wheel_dn_state == 4) 	{wheel_dn_state = 0;
										 old_wheel_state = Wheel_Resting;
										return Wheel_Down;}

		else if (new_wheel_state == 3 || wheel_up_state >= 5 || wheel_dn_state >= 5)
										{wheel_up_state = 0;
										 wheel_dn_state = 0;}
		return Wheel_NoChange;								// No change at this time
}
/****************************************************************************
*			Wheel Pushbutton Retrieval (used for static switch detection)	*
*****************************************************************************/
u08			Get_Button(void)
{
u08 		SW;												// The output
u08			WHEEL;											// Raw pin data - all pins
			WHEEL = inb(WHEEL_SW_PIN);
			SW = WHEEL & (1 << WHEEL_SW);
			if (SW == 1 << WHEEL_SW)		return Button_Up;
			else 							return Button_Down;
}




